<template>
  <!-- 使用 Flex 布局容器 -->
  <div class="flex flex-col w-full">
    <!-- 插槽：用于自定义表格头部 -->
    <slot name="header"></slot>
    <div class="flex items-center mb-4" v-if="slots.btn">
      <slot name="btn"></slot>
    </div>

    <!-- Element Plus 表格组件 -->
    <div class="table-list">
      <el-table
        ref="tableRef"
        :row-key="rowKey"
        :show-header="showHeader"
        :header-cell-style="headerCellStyle"
        :stripe="stripe"
        :fit="fit"
        :data="data"
        v-loading="loading"
        class="custom-table-wrap"
        v-bind="attrs"
      >
        <!-- 动态创建表格列 -->
        <el-table-column v-for="(column, index) in columns" :key="index" :selectable="handleRowSelectable" v-bind="column">
          <!-- 插槽：自定义列内容 -->
          <template v-if="column.slot" #default="scope">
            <slot :name="column.slot" v-bind="scope"></slot>
          </template>
          <!-- 插槽：自定义列头部 -->
          <template v-if="column.slotHeader" #header="scope">
            <slot :name="column.slotHeader" v-bind="scope"></slot>
          </template>
          <!-- 插槽：自定义列筛选图标 -->
          <template v-if="column.slotFilterIcon" #filter-icon="scope">
            <slot :name="column.slotFilterIcon" v-bind="scope"></slot>
          </template>
        </el-table-column>

        <!-- 插槽：自定义表格底部 -->
        <template v-if="slots.append" #append>
          <slot name="append"></slot>
        </template>
        <!-- 插槽：自定义表格为空时的内容 -->
        <template #empty>
          <slot name="empty">
            <div class="flex flex-col justify-center items-center">
              <img v-if="emptySrc" :src="emptySrc" class="table-empty-svg" />
              <p>{{ emptyText }}</p>
            </div>
          </slot>
        </template>
      </el-table>

      <!-- 分页组件 -->
      <div v-if="computedHasPagination" ref="paginationRef" class="flex flex-row-reverse mt-[16px]">
        <el-pagination
          :disabled="loading"
          :current-page="currentPage"
          :page-size="pageSize"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          :page-sizes="[10, 20, 30, 40, 50]"
          @current-change="handlePageChange"
          @size-change="handleSizeChange"
          v-bind="pagination"
        />
      </div>
    </div>

    <!-- 插槽：自定义表格外部内容 -->
    <slot></slot>
  </div>
</template>

<script lang="ts" setup>
import { useSlots, computed, ref, type CSSProperties, useAttrs } from "vue";

import { ElTable, ElTableColumn, ElPagination } from "element-plus";

// 默认图片路径
import defaultEmptyImage from "@/assets/svg/empty.svg?url";

// 组件选项：禁止属性继承
defineOptions({
  inheritAttrs: false
});

// 获取插槽
const slots = useSlots();

// 定义属性接口
interface Props {
  rowKey?: string;
  loading?: boolean; // 表格加载状态
  columns: Record<string, string | number | boolean | object>[]; // 表格列配置数组
  currentPage?: number; // 当前页码
  pageSize?: number; // 每页显示条数
  total?: number; // 数据总条数，用于分页计算
  pagination?: Record<string, number | string | boolean | object>; // 分页组件的额外配置项
  bottom?: number; // 表格整体与底部的间距，默认40
  data: Record<string, string | number | boolean | object>[]; // 表格数据数组
  height?: number | string; // 表格高度，可以是数字或字符串
  showHeader?: boolean; // 是否显示表头
  fit?: boolean; // 列的宽度是否自适应
  headerCellStyle?: CSSProperties; // 表头单元格样式
  stripe?: boolean; // 是否为斑马纹表格
  emptyText?: string; // 表格为空时的提示文字
  emptySrc?: string; //  表格为空时显示的图片路径
  selectableRowKeys?: Array<string | number>;
  selectable?: (row: object, rowIndex: number) => boolean;
}

// 获取传递给组件的属性
const attrs = useAttrs();

// 定义属性默认值
const props = withDefaults(defineProps<Props>(), {
  showHeader: true,
  headerCellStyle: () => ({ background: "#f4f6f8" }),
  stripe: true,
  fit: true,
  bottom: 40,
  emptyText: "暂无数据",
  emptySrc: defaultEmptyImage,
  rowKey: "id"
});

// 定义事件
const emits = defineEmits(["update:currentPage", "update:pageSize", "currentChange", "sizeChange"]);

// 表格引用
const tableRef = ref<InstanceType<typeof ElTable>>();

// 分页引用
const paginationRef = ref<HTMLDivElement>();

// 计算是否有分页
const computedHasPagination = computed(() => props.currentPage && props.pageSize);

const handleRowSelectable = (row: Record<string, string | object | number | boolean>, index: number) => {
  if (props.selectableRowKeys) {
    const rowKey = row[props.rowKey] as string | number;
    return props.selectableRowKeys.includes(rowKey);
  }
  if (props.selectable) {
    return props.selectable(row, index);
  }
  return true;
};

// 更新当前页码
const handlePageChange = (page: number) => {
  emits("update:currentPage", page);
  emits("currentChange", page);
};

// 更新每页大小
const handleSizeChange = (pageSize: number) => {
  emits("update:pageSize", pageSize);
  emits("sizeChange", pageSize);
};

// 暴露方法
defineExpose({
  ref: () => tableRef.value
});
</script>
<style lang="scss" scoped>
.table-list {
  flex: 1;
  min-height: 0;
  .el-table {
    position: relative;
    height: 100%;
    :deep(.el-scrollbar__wrap) {
      display: flex !important;
    }
    .table-empty-svg {
      width: 150px;
      height: 150px;
    }
  }
}
</style>
